package org.elanfox.intellicommunity.biz.service.core.msg.impl;

import org.elanfox.intellicommunity.biz.dto.condition.AlarmGroupSearchCondition;
import org.elanfox.intellicommunity.biz.dto.msg.AlarmOptLogSaveDTO;
import org.elanfox.intellicommunity.biz.dto.msg.AlarmWorkOrderSaveDTO;
import org.elanfox.intellicommunity.biz.entity.msg.AlarmMsgGroupPO;
import org.elanfox.intellicommunity.biz.entity.msg.AlarmMsgGroupPO_;
import org.elanfox.intellicommunity.biz.repository.msg.AlarmMsgGroupRepository;
import org.elanfox.intellicommunity.biz.service.core.msg.AlarmMsgGroupService;
import org.elanfox.intellicommunity.biz.service.core.msg.AlarmMsgOptLogService;
import org.elanfox.intellicommunity.biz.service.core.msg.AlarmWorkOrderService;
import org.elanfox.intellicommunity.common.base.ApiResult;
import org.elanfox.intellicommunity.common.base.ResultCodeEnum;
import org.elanfox.intellicommunity.common.exception.ApiException;
import org.elanfox.intellicommunity.common.ienum.MsgEnums;
import org.elanfox.intellicommunity.common.ienum.base.CodeDescEnumHelper;
import org.elanfox.intellicommunity.common.utils.Jsr310Utils;
import org.elanfox.intellicommunity.data.base.base.AbstractSearchableCrudService;
import org.elanfox.intellicommunity.data.base.base.SpecificationAndSort;
import org.elanfox.intellicommunity.data.base.dto.BaseSaveDTO;
import org.elanfox.intellicommunity.data.base.dto.BaseSearchDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author allan
 * @version 1.0.0
 * @date 2019/12/26
 */
@Service
public class AlarmMsgGroupServiceImpl extends AbstractSearchableCrudService<AlarmMsgGroupPO, Long> implements AlarmMsgGroupService {
    private AlarmMsgGroupRepository alarmMsgGroupRepository;
    @Autowired
    private AlarmMsgOptLogService alarmMsgOptLogService;
    @Autowired
    private AlarmWorkOrderService alarmWorkOrderService;

    @Autowired
    protected AlarmMsgGroupServiceImpl(AlarmMsgGroupRepository repository) {
        super(repository);
        this.alarmMsgGroupRepository = repository;
    }

    @Override
    protected SpecificationAndSort<AlarmMsgGroupPO> specificationAndSort(BaseSearchDTO searchDTO) {
        Specification<AlarmMsgGroupPO> specification = (root, cq, cb) -> {
            AlarmGroupSearchCondition condition = (AlarmGroupSearchCondition) searchDTO;
            List<Predicate> predicates = new ArrayList<>();
            if (!StringUtils.isEmpty(condition.getUserKey())) {
                predicates.add(cb.like(root.get(AlarmMsgGroupPO_.userName), likeAll(condition.getUserKey())));
            }
            if (condition.getAlarmStatus() != -1) {
                MsgEnums.AlarmStatus alarmStatus = CodeDescEnumHelper.getEnumTypeByCode(MsgEnums.AlarmStatus.class, condition.getAlarmStatus());
                predicates.add(cb.equal(root.get(AlarmMsgGroupPO_.alarmStatus), alarmStatus));
            }
            if (!StringUtils.isEmpty(condition.getBeginTime())) {
                LocalDateTime beginTime = Jsr310Utils.DateTime.of(condition.getBeginTime());
                predicates.add(cb.greaterThanOrEqualTo(root.get(AlarmMsgGroupPO_.createTime), beginTime));
            }
            if (!StringUtils.isEmpty(condition.getEndTime())) {
                LocalDateTime endTime = Jsr310Utils.DateTime.of(condition.getEndTime());
                predicates.add(cb.lessThanOrEqualTo(root.get(AlarmMsgGroupPO_.createTime), endTime));
            }

            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };

        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        return new SpecificationAndSort<>(specification, sort);
    }

    @Override
    public AlarmMsgGroupPO save(BaseSaveDTO saveDTO) {
        return null;
    }

    @Override
    @Transactional
    public void onRoad(Long groupId, String policeName, String policeMobile) {
        AlarmMsgGroupPO alarmMsgGroupPO = findById(groupId);
        if (alarmMsgGroupPO.getAlarmStatus() != MsgEnums.AlarmStatus.ALARMING) {
            throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "请检查状态"));
        }

        alarmMsgGroupPO.setAlarmStatus(MsgEnums.AlarmStatus.ON_LOAD);
        save(alarmMsgGroupPO);

        //记录日志
        AlarmOptLogSaveDTO alarmOptLogSaveDTO = AlarmOptLogSaveDTO.builder()
                .alarmStatus(alarmMsgGroupPO.getAlarmStatus())
                .alarmMsgGroupPO(alarmMsgGroupPO)
                .policeMobile(policeMobile)
                .policeName(policeName)
                .build();

        alarmMsgOptLogService.save(alarmOptLogSaveDTO);
    }

    @Override
    @Transactional
    public void handle(Long groupId) {
        AlarmMsgGroupPO alarmMsgGroupPO = findById(groupId);
        if (alarmMsgGroupPO.getAlarmStatus() != MsgEnums.AlarmStatus.ON_LOAD) {
            throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "请检查状态"));
        }
        alarmMsgGroupPO.setAlarmStatus(MsgEnums.AlarmStatus.HANDLED);
        save(alarmMsgGroupPO);

        //记录日志
        AlarmOptLogSaveDTO alarmOptLogSaveDTO = AlarmOptLogSaveDTO.builder()
                .alarmStatus(alarmMsgGroupPO.getAlarmStatus())
                .alarmMsgGroupPO(alarmMsgGroupPO)
                .build();

        alarmMsgOptLogService.save(alarmOptLogSaveDTO);
    }

    @Override
    @Transactional
    public void ignore(Long groupId, String remark) {
        AlarmMsgGroupPO alarmMsgGroupPO = findById(groupId);
        if (alarmMsgGroupPO.getAlarmStatus() != MsgEnums.AlarmStatus.ALARMING) {
            throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "请检查状态"));
        }
        alarmMsgGroupPO.setAlarmStatus(MsgEnums.AlarmStatus.IGNORE);
        save(alarmMsgGroupPO);

        //记录日志
        AlarmOptLogSaveDTO alarmOptLogSaveDTO = AlarmOptLogSaveDTO.builder()
                .alarmStatus(alarmMsgGroupPO.getAlarmStatus())
                .alarmMsgGroupPO(alarmMsgGroupPO)
                .remark(remark)
                .build();

        alarmMsgOptLogService.save(alarmOptLogSaveDTO);
    }

    @Override
    @Transactional
    public void submit(Long groupId, AlarmWorkOrderSaveDTO orderSaveDTO) {
        AlarmMsgGroupPO alarmMsgGroupPO = findById(groupId);
        if (alarmMsgGroupPO.getAlarmStatus() != MsgEnums.AlarmStatus.HANDLED) {
            throw new ApiException(ApiResult.errorWith(ResultCodeEnum.ILLEGAL_STATE, "请检查状态"));
        }
        alarmMsgGroupPO.setAlarmStatus(MsgEnums.AlarmStatus.SUBMITTED);
        alarmMsgGroupPO = save(alarmMsgGroupPO);

        //记录日志
        AlarmOptLogSaveDTO alarmOptLogSaveDTO = AlarmOptLogSaveDTO.builder()
                .alarmStatus(alarmMsgGroupPO.getAlarmStatus())
                .alarmMsgGroupPO(alarmMsgGroupPO)
                .build();

        alarmMsgOptLogService.save(alarmOptLogSaveDTO);

        //保存工单
        orderSaveDTO.setAlarmMsgGroupPO(alarmMsgGroupPO);
        alarmWorkOrderService.save(orderSaveDTO);
    }

    @Override
    public List<AlarmMsgGroupPO> findLastInAlarm() {
        List<MsgEnums.AlarmStatus> list=new ArrayList<>();
        list.add(MsgEnums.AlarmStatus.ALARMING);
        list.add(MsgEnums.AlarmStatus.ON_LOAD);
        return alarmMsgGroupRepository.findByAlarmStatusInOrderByCreateTimeDesc(list);
    }
}
